package fellowship;

import java.awt.Button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import uniqueEquipment.GandalfWeapons;
import equipment.*;
import main.DieRoll;
import main.Equipment;
import main.Hero;
import main.UI;
import main.Unit;
import main.Utils;

public class Gandalf extends Hero {
	public Equipment[] equipChoices = {};
	public boolean hasUsedFreeWill = false;
	
	public Gandalf(int id, int armyIndex, int x, int y) {
		this.strength = 4;
		this.defense = 5;
		this.attacks = 1;
		this.wounds = 3;
		this.courage = 7;
		this.fightValue = 5;
		this.shootValue = 7;
		
		this.might = 3;
		this.will = 6;
		this.fate = 3;
		this.initWorking();

		this.baseMove = 6.0;
		this.move = 6.0;
		this.moveLeft = 6.0;
		
		this.id = id;
		this.name = "Gandalf";
		this.race = "Wizard";
		this.x = x;
		this.y = y;
		this.armyIndex = armyIndex;
		
		this.equip(new GandalfWeapons());
		this.spellList.add("Blinding Light");
		this.spellList.add("Command");
		this.spellList.add("Immobilize");
		this.spellList.add("Sorcerous Blast");
		this.spellList.add("Strengthen Will");
		this.spellList.add("Terrifying Aura");
	}
	
	// Currently only supports cloning at beginning of game (missing some variables that can change throughout game)
	public Gandalf clone() {
		Gandalf copy = new Gandalf(this.id, this.armyIndex, this.x, this.y);
		copy.strength = this.strength;
		copy.defense = this.defense;
		copy.attacks = this.attacks;
		copy.wounds = this.wounds;
		copy.courage = this.courage;
		copy.fightValue = this.fightValue;
		copy.shootValue = this.shootValue;
				
		copy.move = this.move;
		copy.moveLeft = this.moveLeft;
		copy.shootRange = this.shootRange;
		copy.shootStrength = this.shootStrength;
		copy.moveNeededToShoot = this.moveNeededToShoot;
		copy.hasShot = this.hasShot;
		
		copy.equipmentList = new ArrayList<Equipment>();
		for(Equipment e : this.equipmentList){
			copy.equipmentList.add(e);
		}
		
		copy.supporters = new ArrayList<Unit>();
		for(Unit u : this.supporters){
			copy.supporters.add(u);
		}
		
		copy.battle = this.battle;
		copy.game = this.game;
		
		return copy;
	}

	public Equipment[] getEquipChoices() {
		return this.equipChoices;
	}
	
	// These are updated for the Staff of Power rule
	public void useWill(int numDice) {
		if (!this.hasUsedFreeWill && numDice >= 1){
			numDice -= 1;
			this.hasUsedFreeWill = true;
		}
		this.willLeft -= numDice;
	}
	public int getWill() {
		if (!hasUsedFreeWill)
			return willLeft + 1;
		else
			return willLeft;
	}
	public boolean canResist() {
		return willLeft > 0 || !hasUsedFreeWill;
	}
	public void refresh(){
		if (!layingDown)
			this.moveLeft = this.move;
		else
			this.moveLeft = 1;
		this.hasShot = false;
		this.hasFought = false;
		this.passedChargeTest = false;
		this.passedBrokenTest = false;
		this.tempTerrifying = isTerrifying;
		this.isTransfixed = false;
		this.hasUsedMagic = false;
		this.supporting = null;
		this.supporters = new ArrayList<Unit>();
		this.hasRetreated = true;
		
		//Unique to Gandalf: Staff of Power rule
		this.hasUsedFreeWill = false;
		
		if (this.willLeft == 0) {
			this.terrifyingAura = false;
			this.auraOfCommand = false;
			this.hasBlindingLight = false;
		}		
		for (Equipment e : this.equipmentList){
			if (e.options != null)
				e.options.select(0);
		}
		for (Button refreshButton : this.refreshButtons) {
			refreshButton.dispatchEvent(new MouseEvent(refreshButton, MouseEvent.MOUSE_CLICKED, 
					System.currentTimeMillis(), 0, 10, 10, 1, false));
		}
		this.refreshButtons.clear();
	}

	// Updated for Narya (Allow for fate rerolls)
	public void takeStrike(int strength, int roll) {
		if (!Utils.wound(roll, strength, this.getDefense())) {
			return;
		}
		if (this.checkFuryEffect()) {
			int furyRoll = rng.nextInt(6) + 1;
			UI.messageLog.add("Rolling for Fury save (6+): " + furyRoll);
			if (furyRoll >= 6)
				return;
		}
		else if (this.getFate() <= 0) {
			this.takeWound(1);
			if (this.getWounds() <= 0)
				this.die();
			game.myUI.repaint();
		}
		else {
			Button useFate = new Button("Use fate");
			useFate.setName("fateButton");
			useFate.setBounds(game.myUI.dim.width-100, 0, 100, 100);
			
			Button noFate = new Button("Don't use fate");
			noFate.setName("fateButton");
			noFate.setBounds(game.myUI.dim.width-100, 100, 100, 100);
			
			final Unit thisUnit = this;
			
			useFate.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					DieRoll fateRoll = new DieRoll(thisUnit, game.myUI.dim.width-200, game.myUI.dim.height/2-130, "4+ to save", game.myUI);
					fateRoll.makeRerollable();
					useFate(1);
					if (!fateRoll.isModifiable()) {
						int fateNum = fateRoll.getRoll();
						UI.messageLog.add(toChoiceString() + " rolling for fate: " + fateNum);
						game.myUI.removeByName("fateButton");
						game.myUI.reenableComponents();
						fateRoll.cleanup();
						if (fateNum < 4) {
							takeStrike(strength, roll);
						}
						game.myUI.repaint();
					}
					else {
						useFate.setEnabled(false);
						noFate.setEnabled(false);
						ActionListener mightDone = new ActionListener() {
							public void actionPerformed(ActionEvent e) {
								int fateNum = fateRoll.getRoll();
								UI.messageLog.add(toChoiceString() + " rolling for fate: " + fateNum);
								game.myUI.removeByName("fateButton");
								game.myUI.reenableComponents();
								fateRoll.cleanup();
								game.myUI.disableMight();
								if (fateNum < 4) {
									takeStrike(strength, roll);
								}
								game.myUI.repaint();
							}
						};
						game.myUI.enableMight(mightDone);
					}
				}
			});
			
			noFate.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					game.myUI.removeByName("fateButton");
					game.myUI.reenableComponents();
					takeWound(1);
					if (getWounds() <= 0)
						die();
					game.myUI.repaint();
				}
			});
			
			game.myUI.storeVisibleComponents();
			game.myUI.disableComponents();
						
			game.myUI.add(useFate);
			game.myUI.add(noFate);
		}
	}
	public void takeStrike(int strength, int roll, Button doneStriking) {
		if (!Utils.wound(roll, strength, this.getDefense())) {
			if (doneStriking != null)
				doneStriking.dispatchEvent(new MouseEvent(doneStriking, MouseEvent.MOUSE_CLICKED, 
						System.currentTimeMillis(), 0, 10, 10, 1, false));
			game.myUI.repaint();
			return;
		}
		if (this.checkFuryEffect()) {
			int furyRoll = rng.nextInt(6) + 1;
			UI.messageLog.add("Rolling for Fury save (6+): " + furyRoll);
			if (furyRoll >= 6) {
				if (doneStriking != null)
					doneStriking.dispatchEvent(new MouseEvent(doneStriking, MouseEvent.MOUSE_CLICKED, 
							System.currentTimeMillis(), 0, 10, 10, 1, false));
				game.myUI.repaint();
				return;
			}
		}
		else if (this.getFate() <= 0) {
			this.takeWound(1);
			if (this.getWounds() <= 0)
				this.die();
			if (doneStriking != null)
				doneStriking.dispatchEvent(new MouseEvent(doneStriking, MouseEvent.MOUSE_CLICKED, 
						System.currentTimeMillis(), 0, 10, 10, 1, false));
			game.myUI.repaint();
		}
		else {
			game.myUI.storeVisibleComponents();
			game.myUI.disableComponents();
			
			Button useFate = new Button("Use fate");
			useFate.setName("fateButton");
			useFate.setBounds(game.myUI.dim.width-100, 0, 100, 100);
			
			Button noFate = new Button("Don't use fate");
			noFate.setName("fateButton");
			noFate.setBounds(game.myUI.dim.width-100, 100, 100, 100);
			
			final Unit thisUnit = this;
			
			useFate.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					DieRoll fateRoll = new DieRoll(thisUnit, game.myUI.dim.width-200, game.myUI.dim.height/2-130, "4+ to save", game.myUI);
					fateRoll.makeRerollable();
					useFate(1);
					if (!fateRoll.isModifiable()) {
						int fateNum = fateRoll.getRoll();
						UI.messageLog.add(toChoiceString() + " rolling for fate: " + fateNum);
						game.myUI.removeByName("fateButton");
						fateRoll.cleanup();
						if (fateNum < 4) {
							takeStrike(strength, roll, doneStriking);
						}
						else {
							game.myUI.reenableComponents();
							if (doneStriking != null)
								doneStriking.dispatchEvent(new MouseEvent(doneStriking, MouseEvent.MOUSE_CLICKED, 
										System.currentTimeMillis(), 0, 10, 10, 1, false));
						}
						game.myUI.repaint();
					}
					else {
						useFate.setEnabled(false);
						noFate.setEnabled(false);
						ActionListener mightDone = new ActionListener() {
							public void actionPerformed(ActionEvent e) {
								int fateNum = fateRoll.getRoll();
								UI.messageLog.add(toChoiceString() + " rolling for fate: " + fateNum);
								game.myUI.removeByName("fateButton");
								fateRoll.cleanup();
								game.myUI.disableMight();
								if (fateNum < 4) {
									takeStrike(strength, roll, doneStriking);
								}
								else {
									game.myUI.reenableComponents();
									if (doneStriking != null)
										doneStriking.dispatchEvent(new MouseEvent(doneStriking, MouseEvent.MOUSE_CLICKED, 
												System.currentTimeMillis(), 0, 10, 10, 1, false));
								}
								game.myUI.repaint();
							}
						};
						game.myUI.enableMight(mightDone);
					}
				}
			});
			
			noFate.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					game.myUI.removeByName("fateButton");
					game.myUI.reenableComponents();
					takeWound(1);
					if (getWounds() <= 0)
						die();
					if (doneStriking != null)
						doneStriking.dispatchEvent(new MouseEvent(doneStriking, MouseEvent.MOUSE_CLICKED, 
								System.currentTimeMillis(), 0, 10, 10, 1, false));
					game.myUI.repaint();
				}
			});
			
						
			game.myUI.add(useFate);
			game.myUI.add(noFate);
		}
	}
	
}
